package com.ruoyi.category.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.category.mapper.CategoryMapper;
import com.ruoyi.category.service.ICategoryService;
import com.ruoyi.common.annotation.ExecutionType;
import com.ruoyi.common.enums.LogInfoType;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.model.category.Category;
import com.ruoyi.model.category.contest.CategoryVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author : 张怀秋
 **/
@Service
@Slf4j
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements ICategoryService {

    /**
     * 递归查询分类表格
     *
     * @param categoryName 分类名称
     * @return 封装好的树形结构
     */
    @Override
    public List<Category> queryTreeCategoryList(String categoryName) {
//        System.err.println("测试selectPage" +
//                this.baseMapper.selectPage(new Page<>(1, 5), null).getRecords()
//        );
        //1.判断查询参数中是否有值
        //1.1 如果有值那么就返回条件递归列表
        if (StringUtils.isNotEmpty(categoryName)) {
            return new ArrayList<>(this.baseMapper.selectList(Wrappers.<Category>lambdaQuery()
                    .eq(Category::getCategoryName, categoryName)));
        }
        //2. 查询出所有的分类列表
        Map<String, List<Category>> categoryList = this.baseMapper.selectList(null)
                .stream()
                .collect(Collectors.groupingBy(Category::getParentId));
        return burildCategoryTreeList(categoryList, "0");
    }

    /**
     * 构建树形结构
     *
     * @param categories 分类列表
     * @param pId        父id
     * @return 树形列表
     */
    private List<Category> burildCategoryTreeList(Map<String, List<Category>> categories, String pId) {
        return categories.getOrDefault(pId, new ArrayList<>()).stream().map(item ->
                item.setChildren(burildCategoryTreeList(categories, item.getId()))
        ).collect(Collectors.toList());
    }

    /**
     * 删除项目分类
     * 当删的分类有子分类时 不允许删除
     *
     * @param id 分类id
     * @return 影响行数
     */
    @ExecutionType(LogInfoType.DEL)
    @Override
    @Transactional
    public int removeCategoryById(String id) {
        //如果有当被删除的分类有子分类的时候 不允许删除
        //1.查询当前要被删除的分类中是否有子分类
        Long aLong = this.baseMapper.selectCount(Wrappers.<Category>lambdaQuery().eq(Category::getParentId, id));
        if (aLong != 0) {
            throw new RuntimeException("该分类下有子节点 不能被删除哦!");
        }
        //2.没有子节点
        return this.baseMapper.deleteById(id);
    }

    // 非强制移除
    @ExecutionType(LogInfoType.DEL)
    @Override
    @Transactional
    public int removeCategoryNQuit(List<String> ids) {
        int count = 0;
        // 调用上面的方法
        for (String id: ids) {
            count += removeCategoryById(id);
        }

        if (count != ids.size()) {
            throw new RuntimeException("删除失败");
        }

        return 1;
    }

    /**
     * 删除项目分类, 有子分类类可以删除
     *
     * @param id 被删除的id
     * @return 删除成功行数
     * */
    @ExecutionType(LogInfoType.DEL)
    @Override
    @Transactional
    public int removeCategoryByInQuit(String id) {
        /** 当被删除的分类有子分类的时候也允许删除 */
        // 查询出他本身, 并且他是存活的
        Category removeCategory = this.baseMapper.selectOne(Wrappers.
                <Category>lambdaQuery()
                .eq(Category::getId, id)
                .ne(Category::getIsDel, "1"));
        log.warn("{}", removeCategory);
        if (removeCategory == null) { // 不让其删除
            return 0;
        }
        // 查询出他的子分类
        List<Category> categories = this.baseMapper.selectList(Wrappers.<Category>lambdaQuery().eq(Category::getParentId, id));
        if (categories != null) { // 当他有子分类的时候, 需要将其的子分类的父类修改成他的父类
            for (Category category: categories) {
                // 将子分类的父类id改成原来分类的父类id
                category.setParentId(removeCategory.getParentId());
                int checked = this.baseMapper.updateById(category);
                if (checked != 1) { // 只要修改成功的内容不等于1就证明数据有异常, 需要进行处理
                    throw new RuntimeException("修改内容只有"+checked+"个, 异常!!!");
                }
            }
        }

        return this.baseMapper.deleteById(removeCategory);
    }


    /**
     * 删除项目分类, 多个也能删, 强制删除
     *
     * @param ids 要删除的分类集合
     * @return 是否删除成功, 1删除成功, 0删除失败
     * */
    @Override
    @ExecutionType(LogInfoType.DEL)
    @Transactional
    public int removeCategoryQuit(List<String> ids) {
        // 统计删除的个数
        int count = 0;
        // 调用上面删除分类的方法进行处理, 因为每一个被删除的分类如果是某些分类的父类, 则需要将这些分类的父类的修改成他的父类
        for (String id: ids) {
            count += removeCategoryByInQuit(id);
        }

        // 如果有删除失败的分类则都让他删除失败
        if (count != ids.size()) {
            throw new RuntimeException("有些分类删除失败");
        }
        return 1;
    }

    // 修改和增加需要用上的同一个逻辑
    private int checkAndReadCategory(Category category) {
        // 如果能通过名称查询出来分类, 就证明已经有一个这样的分类了
        Long l = this.baseMapper.selectCount(Wrappers.<Category>lambdaQuery().eq(Category::getCategoryName, category.getCategoryName()));
        if (l != 0) {
            return 0;
        }

        // 如果他在某一个地方选择的是顶级结点才会用上
        Category par = this.baseMapper.selectOne(Wrappers.<Category>lambdaQuery().eq(Category::getCategoryName, category.getParentId()));
        if (par != null) {
            category.setParentId(par.getId());
        }
        return 1;
    }

    /**
     * 修改项目分类
     *
     * @param category 分类对象
     * @return 影响行数
     */
    @ExecutionType(LogInfoType.UPD)
    @Override
    public int updateCategoryById(Category category) {
        if (this.checkAndReadCategory(category) == 0) {
            return 0;
        }
        return this.baseMapper.updateById(category);
    }

    /**
     * 新增分类
     *
     * @param category 分类对象
     * @return 影响行数
     */
    @Override
    @ExecutionType(LogInfoType.ADD)
    public int saveCategory(Category category) {
        if (this.checkAndReadCategory(category) == 0) {
            return 0;
        }
        return this.baseMapper.insert(category);
    }

    /**
     * 根据分类名称查询所有的子分类
     *
     * @param categoryName 分类名称
     * @return List<Category>
     */
    @Override
    public List<Category> findCategoryChildListByName(String categoryName) {
        //1.根据名称查询分类
        Category category = this.baseMapper.selectOne(Wrappers.<Category>lambdaQuery().eq(Category::getCategoryName, categoryName));

        //2.根据该分类查询子节点
        List<Category> categoryList = this.baseMapper.selectList(Wrappers.<Category>lambdaQuery().eq(Category::getParentId, category.getId()));

        return categoryList.stream().peek(item -> {
            List<Category> result = this.baseMapper.selectList(Wrappers.<Category>lambdaQuery().eq(Category::getParentId, item.getId()));
            item.setChildren(result);
        }).collect(Collectors.toList());
    }

    /**
     * todo
     * 查询所有分类 并且组装返回
     * （由于需求的变动该接口已经被废弃）
     *
     * @return Map<String, Object>
     */
    @Override
    public Map<String, Object> queryIndexCategory() {
        List<Category> categoryList = this.baseMapper.selectList(null);
        List<Category> faCategoryList = categoryList
                .stream()
                .filter(v -> "0".equals(v.getParentId()))
                .collect(Collectors.toList());
        //我们该系统只有两级分类这里直接返回两级分类即可
        Map<String, Object> map = new HashMap<>();
        faCategoryList.forEach(item -> {
            if (item.getCategoryName().equals("竞赛")) {
                map.put("contestCategoryList", item.setChildren(categoryList
                        .stream()
                        .filter(v -> v.getParentId().equals(item.getId())).collect(Collectors.toList())));
            }
            if (item.getCategoryName().equals("活动")) {
                map.put("activityCategoryList", item.setChildren(categoryList
                        .stream()
                        .filter(v -> v.getParentId().equals(item.getId())).collect(Collectors.toList())));
            }
            if (item.getCategoryName().equals("文章")) {
                map.put("blogCategoryList", item.setChildren(categoryList
                        .stream()
                        .filter(v -> v.getParentId().equals(item.getId())).collect(Collectors.toList())));
            }
        });
        return map;
    }

    /**
     * 查询所有的竞赛分类 (一级)
     *
     * @param categoryName 分类名称
     * @return 展开后的分类
     */
    @Override
    public List<CategoryVo> queryExpandContestCategoryList(String categoryName) {
        List<Category> categories = queryTreeContestCategoryList(null);
        List<Category> reList = new ArrayList<>();
        expand(categories, reList, categoryName);
        List<CategoryVo> categoryVoList = assembleCategoryVoList(reList);
        return categoryVoList;
    }

    // 只保留分类的名称信息
    private List<CategoryVo> assembleCategoryVoList(List<Category> categoryList) {
        // 创建一个展示给前端的分类集合
        List<CategoryVo> categoryVoList = new ArrayList<>();
        // 循环遍历转换分类
        for (Category category : categoryList) {
            categoryVoList.add(assembleCategory(category));
        }
        return categoryVoList;
    }
    private CategoryVo assembleCategory(Category category) {
        CategoryVo categoryVo = new CategoryVo();
        categoryVo.setCategoryName(category.getCategoryName());
        categoryVo.setId(category.getId());
        return categoryVo;
    }

    // 用于展开的递归
    private void expand(List<Category> list, List<Category> reList, String categoryName) {
        if (list == null) {
            return;
        }

        for (Category category : list) {
            List<Category> children = category.getChildren();
            category.setChildren(null);
            if (StringUtils.isBlank(categoryName) || category.getCategoryName().contains(categoryName)) {
                reList.add(category);
            }
            expand(children, reList, categoryName);

        }
     }

    /**
     * 查询所有的竞赛分类
     *
     * @param categoryName 分类名
     * @return List<Category>
     */
    @Override
    public List<Category> queryTreeContestCategoryList(String categoryName) {
        Category contestCategoryOne = this.baseMapper.selectOne(Wrappers.<Category>lambdaQuery()
                .eq(Category::getCategoryName, "竞赛")
                .eq(Category::getParentId, "0"));
        //查询这个数据的所有子数据
        List<Category> treeChildCategoryList = getTreeChildCategoryList(
                this.baseMapper.selectList(null),
                contestCategoryOne.getId()
        );
        if (StringUtils.isNotEmpty(categoryName)) {
            //如果不为空需要根据这个查询
            return treeChildCategoryList.stream().filter(item -> item.getCategoryName().contains(categoryName)).collect(Collectors.toList());
        }
        return treeChildCategoryList;
    }

    /**
     * 获取当前分类下的所有子分类
     *
     * @param categoryList 分类集合
     * @param pId          父id
     * @return List<Category>
     */
    public List<Category> getTreeChildCategoryList(List<Category> categoryList, String pId) {
        return categoryList
                .stream()
                .filter(item -> item.getParentId().equals(pId))
                .map(item -> item.setChildren(getTreeChildCategoryList(categoryList, item.getId())))
                .collect(Collectors.toList());
    }

    /**
     * 查询所有的活动分类
     *
     * @param categoryName 分类名
     * @return List<Category>
     */
    @Override
    public List<Category> queryTreeActivityCategoryList(String categoryName) {
        Category contestCategoryOne = this.baseMapper.selectOne(Wrappers.<Category>lambdaQuery()
                .eq(Category::getCategoryName, "活动")
                .eq(Category::getParentId, "0"));
        //查询这个数据的所有子数据
        List<Category> treeChildCategoryList = getTreeChildCategoryList(
                this.baseMapper.selectList(null),
                contestCategoryOne.getId()
        );
        if (StringUtils.isNotEmpty(categoryName)) {
            //如果不为空需要根据这个查询
            return treeChildCategoryList.stream().filter(item -> item.getCategoryName().equals(categoryName)).collect(Collectors.toList());
        }
        return treeChildCategoryList;
    }

    /**
     * 查询所有的文章分类
     *
     * @param categoryName 分类名
     * @return List<Category>
     */
    @Override
    public List<Category> queryTreeBlogCategoryList(String categoryName) {
        Category contestCategoryOne = this.baseMapper.selectOne(Wrappers.<Category>lambdaQuery()
                .eq(Category::getCategoryName, "文章")
                .eq(Category::getParentId, "0"));
        //查询这个数据的所有子数据
        List<Category> treeChildCategoryList = getTreeChildCategoryList(
                this.baseMapper.selectList(null),
                contestCategoryOne.getId()
        );
        if (StringUtils.isNotEmpty(categoryName)) {
            //如果不为空需要根据这个查询
            return treeChildCategoryList.stream().filter(item -> item.getCategoryName().equals(categoryName)).collect(Collectors.toList());
        }
        return treeChildCategoryList;
    }


}
